package org.sean.framework.exception;

import org.sean.framework.bean.BaseResult;
import org.sean.framework.code.StatusInfo;
import org.sean.framework.context.ApplicationInfo;

/**
 * 状态异常
 */
public class StatusException extends BaseRuntimeException {

    /**
     * 状态信息
     */
    private final StatusInfo statusInfo;

    public StatusException(StatusInfo statusInfo) {
        super(statusInfo.getMessage());
        this.statusInfo = statusInfo;
    }

    public StatusException(StatusInfo statusInfo, Throwable e) {
        super(statusInfo.getMessage(), e);
        this.statusInfo = statusInfo;
    }

    public StatusException(StatusInfo statusInfo, String exceptionMsg, Throwable e) {
        super(exceptionMsg, e);
        this.statusInfo = statusInfo;
    }

    public StatusException(BaseResult<?> result) {
        super(result.getMessage());
        this.statusInfo = new StatusInfo(result.getState()).setAnyMessage(result.getMessage());
    }

    /**
     * 抛出异常
     *
     * @param info 状态信息
     */
    public static void throwException(StatusInfo info) {
        throw new StatusException(info);
    }

    /**
     * @param t 异常
     * @return StatusException
     */
    public static StatusException findStatusException(Throwable t) {
        if (t == null) {
            return null;
        }
        if (StatusException.class.isAssignableFrom(t.getClass())) {
            return (StatusException) t;
        }
        return findThrowable(t.getCause(), StatusException.class);
    }

    /**
     * 设置code
     *
     * @param code 文案
     * @return StatusException
     */
    public StatusException setCode(int code) {
        statusInfo.setCode(code);
        return this;
    }

    /**
     * 设置消息文案
     *
     * @param msgKey  文案
     * @param msgArgs 文案参数
     * @return StatusException
     */
    public StatusException setMessageAndArgs(String msgKey, Object... msgArgs) {
        statusInfo.setMessage(msgKey, msgArgs);
        return this;
    }

    /**
     * 设置级别
     *
     * @param level 级别
     * @return StatusException
     */
    public StatusException setLevel(StatusInfo.Level level) {
        statusInfo.setLevel(level);
        return this;
    }

    /**
     * 获取状态信息
     *
     * @return StatusInfo
     */
    public StatusInfo getStatusInfo() {
        return statusInfo;
    }

    @Override
    public String getMessage() {
        return statusInfo.getMessage();
    }

    /**
     * 设置消息文案
     *
     * @param msgKey 文案
     * @return StatusException
     */
    public StatusException setMessage(String msgKey) {
        statusInfo.setMessage(msgKey);
        return this;
    }

    @Override
    public synchronized Throwable fillInStackTrace() {
        if (ApplicationInfo.showStatusExceptionTrace()) {
            super.fillInStackTrace();
        }
        return this;
    }
}
